package com.Unidbg_hengdin.test;

import com.alibaba.fastjson.util.IOUtils;
import com.github.unidbg.AndroidEmulator;
import com.github.unidbg.Module;
import com.github.unidbg.arm.backend.Backend;
import com.github.unidbg.arm.backend.CodeHook;
import com.github.unidbg.arm.backend.UnHook;
import com.github.unidbg.arm.backend.Unicorn2Factory;
import com.github.unidbg.arm.context.Arm64RegisterContext;
import com.github.unidbg.linux.android.AndroidEmulatorBuilder;
import com.github.unidbg.linux.android.AndroidResolver;
import com.github.unidbg.linux.android.dvm.*;
import com.github.unidbg.linux.android.dvm.array.ByteArray;
import com.github.unidbg.memory.Memory;
import com.github.unidbg.utils.Inspector;
import com.sun.jna.Pointer;

import java.io.File;


public class NativeHelper {
    private final AndroidEmulator emulator;
    private final VM vm;
    private final Module module;

    private final DvmClass NativeHelperUtils;

    private final boolean logging;

    NativeHelper(boolean logging) {
        this.logging = logging;

        emulator = AndroidEmulatorBuilder.for64Bit()
                .setProcessName("com.xiaojianbang.app")
                .addBackendFactory(new Unicorn2Factory(true))
                .build(); // 创建模拟器实例，要模拟32位或者64位，在这里区分
        final Memory memory = emulator.getMemory(); // 模拟器的内存操作接口
        memory.setLibraryResolver(new AndroidResolver(23)); // 设置系统类库解析


        vm = emulator.createDalvikVM(); // 创建Android虚拟机
        vm.setVerbose(logging); // 设置是否打印Jni调用细节      unidbg-android/src/test/java/com/Unidbg_hengdin/ndk/libxiaojianbang.so
//        vm.setJni(new AbstractJni() {
//            @Override
//            public DvmObject<?> callObjectMethodV(BaseVM vm, DvmObject<?> dvmObject, String signature, VaList vaList) {
//                System.out.println("signature ： " + signature);
//                if(signature.equals("java/lang/String->getBytes(Ljava/lang/String;)[B")){
//                    String args = (String)dvmObject.getValue();
//
//                    System.out.println("args :" + args);
//                    byte[] byteArray = args.getBytes();
//                    return new ByteArray(vm,byteArray);
//                }
//                return super.callObjectMethodV(vm, dvmObject, signature, vaList);
//            }
//        });

//        DalvikModule dmA = vm.loadLibrary(new File("unidbg-android/src/test/java/com/Unidbg_hengdin/ndk/libxiaojianbangA.so"), false); // 加载libttEncrypt.so到unicorn虚拟内存，加载成功以后会默认调用init_array等函数
        new XiaojianbangA(emulator,vm).register(memory);
        DalvikModule dm = vm.loadLibrary(new File("unidbg-android/src/test/java/com/Unidbg_hengdin/test/libxiaojianbang.so"), false); // 加载libttEncrypt.so到unicorn虚拟内存，加载成功以后会默认调用init_array等函数
        dm.callJNI_OnLoad(emulator); // 手动执行JNI_OnLoad函数
        module = dm.getModule(); // 加载好的libttEncrypt.so对应为一个模块

        NativeHelperUtils = vm.resolveClass("com/xiaojianbang/ndk/NativeHelper");
    }

    void destroy() {
        IOUtils.close(emulator);
        if (logging) {
            System.out.println("destroy");
        }
    }

    public static void main(String[] args) throws Exception {
        NativeHelper test = new NativeHelper(true);

//        int data = test.callFun();
        test.callFun();

//        Inspector.inspect(data, "callFun");
//
        test.destroy();
    }

    void callFun() {

//        byte[] data = new byte[16];

//        调用 add 方法
//        int retval = NativeHelperUtils.callStaticJniMethodInt(emulator, "add(III)I", 0x100, 0x200, 0x300); // 执行Jni方法
//        System.out.println("res : 0x" + Integer.toHexString(retval));

//        调用MD5方法
//        StringObject md5_retval = NativeHelperUtils.callStaticJniMethodObject(emulator, "md5(Ljava/lang/String;)Ljava/lang/String;", new StringObject(vm,"123456")); // 执行Jni方法
//        System.out.println("md5_retval res : " + md5_retval.getValue());

//        调用encode 方法
        StringObject encodeRetval = NativeHelperUtils.callStaticJniMethodObject(emulator, "encode()Ljava/lang/String;"); // 执行Jni方法
        System.out.println("encodeRetval res : " + encodeRetval.getValue());


    }

}
